﻿#ifndef SMARTMENU_H
#define SMARTMENU_H

#include "m_fhs.h"
#include <head/g_pch.h>
#include <head/g_function.h>
#include <head/db_helper.h>
#include <support/sp_env.h>
#include "support/pie.h"
#include <support/mysql_helper.h>
#include <boot/g_bootfunction.h>
#include <element/simpleconfigurator.h>

#ifdef Q_OS_WIN
#include "support/reg_winver.h"
#endif

class SmartMenu : public QMenu
{
    Q_OBJECT
public:
    explicit SmartMenu(QWidget *parent =nullptr): QMenu(parent)
    {
        m_favorite=nullptr;
    }

    void setConfigurator(const SimpleConfigurator &config_)
    {
        config=config_;
    }

    void generateMenu()
    {
        createLauncherMenu();
        createLocationMenu();
        createAppMenu();
        createPropsMenu();
        createToolMenu();
        createSysToolMenu();
        createCommandMenu();
        createToolboxMenu();
        createFavoriteMenu();
        createOptionMenu();
    }

    void setStartup()
    {
        ::sp_setStartup(true);
    }

    void unsetStartup()
    {
        ::sp_setStartup(false);
    }

    void aboutVersion()
    {
        QString info=QStringLiteral("附加信息：\n");
        ::sp_aboutVersionAddition(info);
    }

    void showHardwareInfo()
    {
        QString macAddress=::sp_getHarewareAddress().join(",");
        QString info=QStringLiteral("CPU：\n") + ::reg_getCPUName() + "\n"
                + QStringLiteral("主板：\n") + ::reg_getBIOSInfo() + "\n"
                + QStringLiteral("物理地址: \n") + macAddress;
        QMessageBox::information(0,QStringLiteral("硬件信息"), info);
    }

    void fetchExternalIpInfo()
    {
        emit fetchExternalIp();
    }

    void createLauncherMenu()
    {
        if(!config.isLauncher)
            return;

        QMenu *m_launcher=this->addMenu("启动器");
        QSqlQuery query;
        query.exec(QString(SELECT_VARS).arg(P_LAUNCHER).arg(MT_PROGRAM));
        if(query.size() > 0)
        {
            QMenu *progMenu=m_launcher->addMenu(MT_PROGRAM);
            while (query.next()) {
                QString label=query.value(0).toString();
                QString detail=query.value(1).toString();
                progMenu->addAction(label)->setData(detail);
            }
        }

        query.exec(QString(SELECT_VARS).arg(P_LAUNCHER).arg(MT_LOCATION));
        if(query.size() > 0)
        {
            QMenu *locationMenu=m_launcher->addMenu(MT_LOCATION);
            while (query.next()) {
                QString label=query.value(0).toString();
                QString detail=query.value(1).toString();
                locationMenu->addAction(label)->setData(detail);
            }
        }

        query.exec(QString(SELECT_VARS).arg(P_LAUNCHER).arg(MT_FILE));
        if(query.size() > 0)
        {
            QMenu *fileMenu=m_launcher->addMenu(MT_FILE);
            while (query.next()) {
                QString label=query.value(0).toString();
                QString detail=query.value(1).toString();
                fileMenu->addAction(label)->setData(detail);
            }
        }

        if(!m_launcher->isEmpty())
            connect(m_launcher,&QMenu::triggered,this,&SmartMenu::processPropsAction);

        this->addSeparator();
    }

    void createOptionMenu()
    {
        this->addSeparator();
        QMenu *m_option=this->addMenu(QStringLiteral("选项"));

        QMenu *infoMenu=m_option->addMenu("信息");
        infoMenu->addAction(QStringLiteral("本机信息"),::sp_aboutDevice);
        infoMenu->addAction(QStringLiteral("应用信息"),::sp_aboutApp);
        infoMenu->addAction(QStringLiteral("版本信息"),this,&SmartMenu::aboutVersion);
        infoMenu->addAction(QStringLiteral("硬件信息"),this,&SmartMenu::showHardwareInfo);
        infoMenu->addAction(QStringLiteral("外网IP"),this,);

        QMenu *m_skin=m_option->addMenu(QStringLiteral("换肤"));
        m_skin->addAction(QStringLiteral("蓝星"));
        m_skin->addAction(QStringLiteral("绿星"));
        m_skin->addAction(QStringLiteral("粉星"));
        connect(m_skin,&QMenu::triggered,this,&SmartMenu::processsSkinAction);

        QMenu *advMenu=m_option->addMenu("高级");
        advMenu->addAction("重建菜单",this,&SmartMenu::rebuild);
        advMenu->addSeparator();
        advMenu->addAction(QStringLiteral("设置开机启动"),this,&SmartMenu::setStartup);
        advMenu->addAction(QStringLiteral("取消开机启动"),this,&SmartMenu::unsetStartup);

        m_option->addSeparator();
        m_option->addAction(QStringLiteral("退出"),QApplication::quit);
    }

    void rebuild()
    {
        emit reloadMenu();
    }

    void processsSkinAction(QAction *action)
    {
        if(action->text() == QStringLiteral("蓝星"))
            emit changeSkin(sk_blu);
        else if(action->text() == QStringLiteral("粉星"))
            emit changeSkin(sk_pik);
        else if(action->text() == QStringLiteral("绿星"))
            emit changeSkin(sk_gre);
    }

    void createSysToolMenu()
    {
        if(!config.isAdvanced)
            return;

        QSqlQuery query;
        QString sql=QString(MENU_GET_VARS).arg(T_SYSTOOL);
        query.exec(sql);
        if(query.size() < 1)
            return;

        QMenu *m_sysTool=this->addMenu(QStringLiteral("系统工具"));
        while(query.next())
        {
            QString label=query.value(0).toString();
            QString detail=query.value(1).toString();
            m_sysTool->addAction(label)->setData(detail);
        }
        connect(m_sysTool,&QMenu::triggered,this,&SmartMenu::processMenuAction);
    }

    void createPropsMenu()
    {
        QMenu *m_props=this->addMenu(QStringLiteral("组件"));
        m_props->addAction(QStringLiteral("速记1 (Alt+1)"),this,&SmartMenu::showNote);
        m_props->addAction(QStringLiteral("速记2 (Alt+2)"),this,&SmartMenu::showNote2);
        m_props->addAction(QStringLiteral("速搜 (Alt+F2)"),this,&SmartMenu::showSearchBox);
        m_props->addAction(QStringLiteral("计算器 (F3)"),this,&SmartMenu::invokeCalc);

        QSqlQuery query;
        QString sql=QString(MENU_GET_VARS).arg(T_PROPS);
        query.exec(sql);
        if(query.size() < 1)
            return;

        m_props->addSeparator();
        while(query.next())
        {
            QString label=query.value(0).toString();
            QString detail=query.value(1).toString();
            m_props->addAction(label)->setData(detail);
        }
        connect(m_props,&QMenu::triggered,this,&SmartMenu::processPropsAction);
    }

    void showNote()
    {
        emit invokeProp(ID_NOTE);
    }

    void showNote2()
    {
        emit invokeProp(ID_NOTE2);
    }

    void showSearchBox()
    {
        emit invokeProp(ID_SEARCHBOX);
    }

    void invokeCalc()
    {
        emit invokeProp(ID_CALC);
    }

    void createAppMenu()
    {
        QSqlQuery query;
        QString sql=QString(MENU_GET_VARS).arg(T_APP);
        query.exec(sql);
        if(query.size() < 1)
            return;

        QMenu *m_app=this->addMenu("应用");
        while(query.next())
        {
            QString label=query.value(0).toString();
            QString detail=query.value(1).toString();
            m_app->addAction(label)->setData(detail);
        }
        connect(m_app,&QMenu::triggered,this,&SmartMenu::processMenuAction);
    }

    void createCommandMenu()
    {
        QSqlQuery query;
        QString sql=QString(MENU_GET_VARS).arg(T_COMMAND);
        query.exec(sql);
        if(query.size() < 1)
            return;

        QMenu *m_command=this->addMenu(QStringLiteral("命令"));
        while(query.next())
        {
            QString label=query.value(0).toString();
            QString detail=query.value(1).toString();
            m_command->addAction(label)->setData(detail);
        }
        connect(m_command,&QMenu::triggered,this,&SmartMenu::processMenuAction);
    }

    void createLocationMenu()
    {
        QMenu *m_location=this->addMenu(QStringLiteral("位置"));
        if(config.isAdvanced)
        {
            m_location->addAction("configLocation")->setData(Location::configLocation);
            m_location->addAction("dataLocation")->setData(Location::dataLocation);
            m_location->addAction("cacheLocation")->setData(Location::cacheLocation);
            m_location->addAction("genericDataLocation")->setData(Location::genericDataLocation);
        }

        QSqlQuery query;
        QString sql=QString(MENU_GET_VARS).arg(T_LOCATION);
        query.exec(sql);
        if(query.size() < 1)
            return;

        m_location->addSeparator();
        while(query.next())
        {
            QString label=query.value(0).toString();
            QString detail=query.value(1).toString();
            m_location->addAction(label)->setData(detail);
        }

        sql=QString(MENU_GET_VARS).arg(T_LOCATION_LOW);
        query.exec(sql);
        if(query.size() < 1)
            return;

        m_location->addSeparator();
        while(query.next())
        {
            QString label=query.value(0).toString();
            QString detail=query.value(1).toString();
            m_location->addAction(label)->setData(detail);
        }

        connect(m_location,&QMenu::triggered,this,&SmartMenu::processLocationAction);
    }

    void createToolMenu()
    {
        QSqlQuery query;
        QString sql=QString(MENU_GET_VARS).arg(T_TOOL);
        query.exec(sql);
        if(query.size() < 1)
            return;

        QMenu *m_tool=this->addMenu(QStringLiteral("工具"));
        while(query.next())
        {
            QString label=query.value(0).toString();
            QString detail=query.value(1).toString();
            m_tool->addAction(label)->setData(detail);
        }
        connect(m_tool,&QMenu::triggered,this,&SmartMenu::processMenuAction);
    }

    void createToolboxMenu()
    {
        if(!config.isUtility)
            return;

        QDir dir(FHS_OPT);
        if(!dir.exists())
            return;

        QStringList dirList=dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
        if(dirList.size() < 1)
            return;

        QMenu *m_toolbox=this->addMenu(QStringLiteral("工具箱"));
        foreach (QString folder, dirList) {
            folder = P_FHS_OPT + folder;
            QString propFile=folder + "/prop.json";
            if(QFile::exists(propFile)){
                Pie pie;
                if(pie.load(propFile))
                {
                    QString label=pie.value("label").toString();
                    QString entry=folder + QString("/")  + pie.value("entry").toString();
                    m_toolbox->addAction(label)->setData(entry);
                }
            }
        }
        connect(m_toolbox,&QMenu::triggered,this,&SmartMenu::processToolboxAction);
    }

    void reloadToolboxMenu();
    void watchOptDirectory();

    void createFavoriteMenu()
    {
        if(!config.isFavorite)
            return;

        this->addSeparator();
        if(m_favorite != nullptr)
        {
            m_favorite->clear();
            m_favorite->disconnect();
            m_favorite=nullptr;
        }
        m_favorite=this->addMenu(QStringLiteral("收藏夹"));
        createFavoriteMenuItem();

    }
    void createFavoriteMenuItem()
    {
        auto topics=sp_getTopic(P_SITE);
        foreach (auto topic, topics) {
            QMenu *topicMenu=m_favorite->addMenu(topic);
            QSqlQuery query;
            QString sql=QString("select label,detail from %1 where topic='%2'")
                    .arg(P_SITE)
                    .arg(topic);
            query.exec(sql);
            while (query.next()) {
                QString label=query.value("label").toString();
                QString detail=query.value("detail").toString();
                topicMenu->addAction(label)->setData(detail);
            }
        }
        m_favorite->addSeparator();
        m_favorite->addAction(QStringLiteral("刷新"),
                              this,&SmartMenu::reloadFavoriteMenu);
        connect(m_favorite,&QMenu::triggered,this,&SmartMenu::processFavoriteAction);
    }

    void reloadFavoriteMenu()
    {
        m_favorite->clear();
        m_favorite->disconnect();
        createFavoriteMenuItem();
        emit say("收藏夹已刷新");
    }

    void processMenuAction(QAction *action)
    {
        QString detail=action->data().toString();
        if(detail.isEmpty())
            return;

        if(!detail.contains(" "))
            QDesktopServices::openUrl(QUrl(detail));
        else
            QProcess::startDetached(detail,QStringList());
    }

    void processPropsAction(QAction *action)
    {
        QString detail=action->data().toString();
        if(detail.isEmpty())
            return;

        if(!QFile::exists(detail))
            return;

        if(!detail.contains(" "))
            QDesktopServices::openUrl(QUrl::fromLocalFile(detail));
        else
            QProcess::startDetached(detail,QStringList());
    }

    void processLocationAction(QAction *action)
    {
        QString detail=action->data().toString();
        if(detail.isEmpty())
            return;

        if(detail.startsWith("%") || detail.startsWith("shell:"))
            QProcess::startDetached(SHELL_OPEN,QStringList()<<detail);
        else
            QDesktopServices::openUrl(QUrl(detail));
    }

    void processFavoriteAction(QAction *action)
    {
        QString detail=action->data().toString();
        if(detail.isEmpty())
            return;

        QDesktopServices::openUrl(QUrl(detail));
    }

    void processToolboxAction(QAction *action)
    {
        QString detail=action->data().toString();
        if(detail.isEmpty())
            return;

        if(QFile::exists(detail))
            QDesktopServices::openUrl(QUrl::fromLocalFile(detail));
    }

signals:
    void say(const QString &message,unsigned sec=4);
    void invokeProp(int propId);
    void changeSkin(int skinId);
    void reloadMenu();
    void fetchExternalIp();

private:
    SimpleConfigurator config;
    QMenu *m_favorite;
};

#endif // SMARTMENU_H
